package com.dataconver.sync;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.dataconver.db.DatabaseManager;

/**
 * 数据同步器
 * 负责执行具体的数据同步任务
 */
@Component
public class DataSynchronizer {
    private static final Logger logger = LoggerFactory.getLogger(DataSynchronizer.class);
    
    /**
     * 执行所有表的同步
     * @return 同步结果
     */
    public SyncResult syncAll() {
        SyncResult totalResult = new SyncResult();
        totalResult.setStartTime(System.currentTimeMillis());
        totalResult.setTableName("ALL_TABLES");
        
        int totalProcessed = 0;
        int totalInserted = 0;
        int totalUpdated = 0;
        boolean allSuccess = true;
        StringBuilder errorMessages = new StringBuilder();
        
        try {
            // 1. 同步第一张表：wm_mulity_route
            logger.info("=== 开始同步第一张表: MulityRoute -> wm_mulity_route ===");
            logger.info("处理条件: 全量同步，按IMEI字段进行UPSERT操作");
            logger.info("预计处理数据量: 约6000条记录");
            SyncResult result1 = syncMulityRouteTable();
            if (result1.isSuccess()) {
                logger.info("✅ wm_mulity_route 同步成功 - 处理: {} 条, 插入: {} 条, 更新: {} 条", 
                    result1.getProcessedRows(), result1.getInsertedRows(), result1.getUpdatedRows());
                totalProcessed += result1.getProcessedRows();
                totalInserted += result1.getInsertedRows();
                totalUpdated += result1.getUpdatedRows();
            } else {
                logger.error("❌ wm_mulity_route 同步失败: {}", result1.getErrorMessage());
                allSuccess = false;
                errorMessages.append("wm_mulity_route: ").append(result1.getErrorMessage()).append("; ");
            }
            
            // 2. 同步第二张表：wm_mulity_route_his
            logger.info("=== 开始同步第二张表: MulityRoute_His -> wm_mulity_route_his ===");
            logger.info("处理条件: 增量同步，按systime时间戳过滤，仅同步新增数据");
            logger.info("预计处理数据量: 根据增量时间确定");
            SyncResult result2 = syncMulityRouteHisTable();
            if (result2.isSuccess()) {
                logger.info("✅ wm_mulity_route_his 同步成功 - 处理: {} 条, 插入: {} 条, 更新: {} 条", 
                    result2.getProcessedRows(), result2.getInsertedRows(), result2.getUpdatedRows());
                totalProcessed += result2.getProcessedRows();
                totalInserted += result2.getInsertedRows();
                totalUpdated += result2.getUpdatedRows();
            } else {
                logger.error("❌ wm_mulity_route_his 同步失败: {}", result2.getErrorMessage());
                allSuccess = false;
                errorMessages.append("wm_mulity_route_his: ").append(result2.getErrorMessage()).append("; ");
            }
            
            // 3. 同步第三张表：wm_mulity_route_meter_data
            logger.info("=== 开始同步第三张表: MulityRoutMeterData -> wm_mulity_route_meter_data ===");
            logger.info("处理条件: 关联增量同步，根据wm_mulity_route_his新增记录ID查询对应仪表数据");
            logger.info("预计处理数据量: 根据关联记录数量确定");
            SyncResult result3 = syncMeterDataTable();
            if (result3.isSuccess()) {
                logger.info("✅ wm_mulity_route_meter_data 同步成功 - 处理: {} 条, 插入: {} 条, 更新: {} 条", 
                    result3.getProcessedRows(), result3.getInsertedRows(), result3.getUpdatedRows());
                totalProcessed += result3.getProcessedRows();
                totalInserted += result3.getInsertedRows();
                totalUpdated += result3.getUpdatedRows();
            } else {
                logger.error("❌ wm_mulity_route_meter_data 同步失败: {}", result3.getErrorMessage());
                allSuccess = false;
                errorMessages.append("wm_mulity_route_meter_data: ").append(result3.getErrorMessage()).append("; ");
            }
            
            // 设置总结果
            totalResult.setProcessedRows(totalProcessed);
            totalResult.setInsertedRows(totalInserted);
            totalResult.setUpdatedRows(totalUpdated);
            totalResult.setSuccess(allSuccess);
            if (!allSuccess) {
                totalResult.setErrorMessage(errorMessages.toString());
            }
            
            // 所有表同步完成后，统一更新同步状态
            if (allSuccess) {
                try {
                    updateAllSyncStatus();
                } catch (Exception e) {
                    logger.error("更新同步状态失败", e);
                }
            }
            
        } catch (Exception e) {
            logger.error("执行所有表同步时发生异常", e);
            totalResult.setSuccess(false);
            totalResult.setErrorMessage("执行异常: " + e.getMessage());
        } finally {
            totalResult.setEndTime(System.currentTimeMillis());
        }
        
        return totalResult;
    }
    
    /**
     * 执行UPSERT同步
     * @param sourceTable 源表名
     * @param targetTable 目标表名
     * @param keyField 关键字段
     * @return 同步结果
     */
    public static SyncResult syncWithUpsert(String sourceTable, String targetTable, String keyField) {
        try {
            UpsertSyncStrategy strategy = new UpsertSyncStrategy(sourceTable, keyField, targetTable);
            return strategy.execute(targetTable);
        } catch (Exception e) {
            logger.error("UPSERT同步失败: {} -> {}", sourceTable, targetTable, e);
            SyncResult result = new SyncResult();
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            return result;
        }
    }
    
    /**
     * 执行MulityRoute到wm_mulity_route的同步
     * @return 同步结果
     */
    public static SyncResult syncMulityRouteTable() {
        return syncWithUpsert("MulityRoute", "wm_mulity_route", "IMEI");
    }

    /**
     * 执行 wm_mulity_route_his 增量同步
     */
    public static SyncResult syncMulityRouteHisTable() {
        try {
            IncrementalHisSyncStrategy strategy = new IncrementalHisSyncStrategy();
            return strategy.execute("wm_mulity_route_his");
        } catch (Exception e) {
            logger.error("wm_mulity_route_his 增量同步失败", e);
            SyncResult result = new SyncResult();
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            return result;
        }
    }

    /**
     * 执行 wm_mulity_route_meter_data 关联增量同步
     */
    public static SyncResult syncMeterDataTable() {
        try {
            RelatedMeterSyncStrategy strategy = new RelatedMeterSyncStrategy();
            return strategy.execute("wm_mulity_route_meter_data");
        } catch (Exception e) {
            logger.error("wm_mulity_route_meter_data 关联增量同步失败", e);
            SyncResult result = new SyncResult();
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            return result;
        }
    }
    
    // 保持向后兼容的方法名
    @Deprecated
    public static SyncResult syncMulityRoute() {
        return syncMulityRouteTable();
    }
    
    @Deprecated
    public static SyncResult syncMulityRouteHisIncremental() {
        return syncMulityRouteHisTable();
    }
    
    @Deprecated
    public static SyncResult syncMeterDataRelatedIncremental() {
        return syncMeterDataTable();
    }
    
    /**
     * 更新所有表的同步状态
     * 在所有表同步成功后统一调用
     */
    private static void updateAllSyncStatus() throws SQLException {
        try (Connection conn = DatabaseManager.getMysqlConnection()) {
            // 更新 wm_mulity_route 同步状态
            updateTableSyncStatus(conn, "wm_mulity_route");
            
            // 更新 wm_mulity_route_his 同步状态
            updateTableSyncStatus(conn, "wm_mulity_route_his");
            
            // 更新 wm_mulity_route_meter_data 同步状态
            updateTableSyncStatus(conn, "wm_mulity_route_meter_data");
        }
    }
    
    /**
     * 更新单个表的同步状态
     */
    private static void updateTableSyncStatus(Connection conn, String tableName) throws SQLException {
        String upsert = "INSERT INTO wm_sync_status(table_name,last_sync_time,updated_time) VALUES(?,NOW(),NOW()) " +
                "ON DUPLICATE KEY UPDATE last_sync_time=NOW(), updated_time=NOW()";
        
        try (PreparedStatement ps = conn.prepareStatement(upsert)) {
            ps.setString(1, tableName);
            ps.executeUpdate();
        }
    }
}
